#include "debug.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <uci.h>
#include "popen_interface.h"


int PopenInf_SetTime(popenInfTimeType_t type, uint16_t value)
{
    FILE *fp;
    char bufGet[32] = {0}, bufSet[64] = {0};
    char bufPrefix[32] = {0}, bufSuffix[32] = {0};

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        POPENINF_TIME_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -1;
    }

    if((fp = popen("date \"+\%Y-\%m-\%d \%H:\%M:\%S\"", "r")) == NULL)
    {
        PRINT_WARN("Get failure");
        return -1;
    }
    fread(bufGet, sizeof(char), 32, fp);
    pclose(fp);

    switch(type)
    {
        case POPENINF_TIME_TYPE_YEAR:
            if(value < 1970 || value > 2038)
            {
                PRINT_WARN("Parameter error[%d]", type);
                return -1;
            }
            strncpy(bufSuffix, &bufGet[4], 15);
            snprintf(bufSet, 64, "date -s \"%04d%.15s\"", value, bufSuffix);
            break;

        case POPENINF_TIME_TYPE_MON:
            if(value > 12)
            {
                PRINT_WARN("Parameter error[%d]", type);
                return -1;
            }
            strncpy(bufPrefix, bufGet, 5);
            strncpy(bufSuffix, &bufGet[7], 12);
            snprintf(bufSet, 64, "date -s \"%.5s%02d%.12s\"", bufPrefix, value, bufSuffix);
            break;
            
        case POPENINF_TIME_TYPE_DATE:
            if(value > 31)
            {
                PRINT_WARN("Parameter error[%d]", type);
                return -1;
            }
            strncpy(bufPrefix, bufGet, 8);
            strncpy(bufSuffix, &bufGet[10], 9);
            snprintf(bufSet, 64, "date -s \"%.8s%02d%.9s\"", bufPrefix, value, bufSuffix);
            break;
            
        case POPENINF_TIME_TYPE_HOUR:
            if(value > 23)
            {
                PRINT_WARN("Parameter error[%d]", type);
                return -1;
            }
            strncpy(bufPrefix, bufGet, 11);
            strncpy(bufSuffix, &bufGet[13], 6);
            snprintf(bufSet, 64, "date -s \"%.11s%02d%.6s\"", bufPrefix, value, bufSuffix);
            break;
            
        case POPENINF_TIME_TYPE_MIN:
            if(value > 59)
            {
                PRINT_WARN("Parameter error[%d]", type);
                return -1;
            }
            strncpy(bufPrefix, bufGet, 14);
            strncpy(bufSuffix, &bufGet[16], 3);
            snprintf(bufSet, 64, "date -s \"%.14s%02d%.3s\"", bufPrefix, value, bufSuffix);
            break;
            
        case POPENINF_TIME_TYPE_SEC:
            if(value > 59)
            {
                PRINT_WARN("Parameter error[%d]", type);
                return -1;
            }
            strncpy(bufPrefix, bufGet, 17);
            snprintf(bufSet, 64, "date -s \"%.17s%02d\"", bufPrefix, value);
            break;
            
        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -1;
    }

    PRINT_DEBUG("%s", bufSet);

    if((fp = popen(bufSet, "w")) == NULL)
    {
        PRINT_WARN("Set failure");
        return -1;
    }
    pclose(fp);

    if(type == POPENINF_TIME_TYPE_SEC)
    {
        if((fp = popen("hwclock -wu", "w")) == NULL)
        {
            PRINT_WARN("Set failure");
            return -1;
        }
        pclose(fp);
    }
    
    return 0;
}


int PopenInf_GetNetParam(popenInfNetParamType_t type, uint16_t *pValue)
{
    FILE *fp;
    char *pCmd = NULL;
    char buf[8] = {0};
    uint16_t flagMac = 0;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        POPENINF_NET_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -1;
    }

    switch(type)
    {
        case POPENINF_NET_PARAM_TYPE_PORT1_IP0:
            pCmd = "ifconfig eth0 | awk 'NR==2{print $2}' | grep -oE '[0-9]{1,3}' | awk 'NR==1'";
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_IP1:
            pCmd = "ifconfig eth0 | awk 'NR==2{print $2}' | grep -oE '[0-9]{1,3}' | awk 'NR==2'";
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_IP2:
            pCmd = "ifconfig eth0 | awk 'NR==2{print $2}' | grep -oE '[0-9]{1,3}' | awk 'NR==3'";
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_IP3:
            pCmd = "ifconfig eth0 | awk 'NR==2{print $2}' | grep -oE '[0-9]{1,3}' | awk 'NR==4'";
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_MAC0:
            pCmd = "ifconfig eth0 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==1'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_MAC1:
            pCmd = "ifconfig eth0 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==2'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_MAC2:
            pCmd = "ifconfig eth0 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==3'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_MAC3:
            pCmd = "ifconfig eth0 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==4'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_MAC4:
            pCmd = "ifconfig eth0 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==5'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT1_MAC5:
            pCmd = "ifconfig eth0 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==6'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_IP0:
            pCmd = "ifconfig eth1 | awk 'NR==2{print $2}' | grep -oE '[0-9]{1,3}' | awk 'NR==1'";
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_IP1:
            pCmd = "ifconfig eth1 | awk 'NR==2{print $2}' | grep -oE '[0-9]{1,3}' | awk 'NR==2'";
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_IP2:
            pCmd = "ifconfig eth1 | awk 'NR==2{print $2}' | grep -oE '[0-9]{1,3}' | awk 'NR==3'";
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_IP3:
            pCmd = "ifconfig eth1 | awk 'NR==2{print $2}' | grep -oE '[0-9]{1,3}' | awk 'NR==4'";
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_MAC0:
            pCmd = "ifconfig eth1 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==1'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_MAC1:
            pCmd = "ifconfig eth1 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==2'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_MAC2:
            pCmd = "ifconfig eth1 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==3'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_MAC3:
            pCmd = "ifconfig eth1 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==4'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_MAC4:
            pCmd = "ifconfig eth1 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==5'";
            flagMac = 1;
            break;

        case POPENINF_NET_PARAM_TYPE_PORT2_MAC5:
            pCmd = "ifconfig eth1 | awk 'NR==1{print $5}' | grep -oE '[A-Za-z0-9]{1,2}' | awk 'NR==6'";
            flagMac = 1;
            break;
            
        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -1;
    }

    if((fp = popen(pCmd, "r")) == NULL)
    {
        PRINT_WARN("Get failure");
        return -1;
    }

    fread(buf, sizeof(char), 8, fp);
    if(flagMac == 0)
    {
        *pValue = atoi(buf);
    }
    else
    {
        sscanf(buf, "%x", (uint32_t *)pValue);
    }
    pclose(fp);
    
    return 0;
}


int PopenInf_SetIp(popenInfPortIdx_t idx, uint16_t *pValueArr)
{
    PRINT_DEBUG();
    FILE *fp;
    char bufSet[128] = {0};

    switch(idx)
    {
    #define X_MACRO(a, b) case a:
        POPENINF_PORT_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", idx);
            return -1;
    }

    if(pValueArr[0] > 255 || pValueArr[1] > 255 || \
       pValueArr[2] > 255 || pValueArr[3] > 255)
    {
        PRINT_WARN("Parameter error[%d]", idx);
        return -1;
    }

    switch(idx)
    {
        case POPENINF_PORT_1:
            // PRINT_WARN("%d.%d.%d.%d", pValueArr[0], pValueArr[1], pValueArr[2], pValueArr[3]);
            sprintf(bufSet, "uci set network.lan.ipaddr='%d.%d.%d.%d'", pValueArr[0], pValueArr[1], pValueArr[2], pValueArr[3]);
            break;

        case POPENINF_PORT_2:
            // PRINT_WARN("%d.%d.%d.%d", pValueArr[0], pValueArr[1], pValueArr[2], pValueArr[3]);
            sprintf(bufSet, "uci set network.wan.ipaddr='%d.%d.%d.%d'", pValueArr[0], pValueArr[1], pValueArr[2], pValueArr[3]);
            break;

        case POPENINF_PORT_3:
        case POPENINF_PORT_4:
            break;
            
        default:
            PRINT_WARN("Parameter error[%d]", idx);
            return -1;
    }

    PRINT_DEBUG("%s", bufSet);

    if((fp = popen(bufSet, "w")) == NULL)
    {
        PRINT_WARN("Set failure");
        return -1;
    }
    pclose(fp);
    
    return 0;
}


int PopenInf_SetMac(popenInfPortIdx_t idx, uint16_t *pValueArr)
{
    FILE *fp;
    char bufSet[128] = {0};

    switch(idx)
    {
    #define X_MACRO(a, b) case a:
        POPENINF_PORT_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", idx);
            return -1;
    }

    if(pValueArr[0] > 255 || pValueArr[1] > 255 || pValueArr[2] > 255 || \
       pValueArr[3] > 255 || pValueArr[4] > 255 || pValueArr[5] > 255)
    {
        PRINT_WARN("Parameter error[%d]", idx);
        return -1;
    }

    switch(idx)
    {
        case POPENINF_PORT_1:
            // PRINT_DEBUG("%02x:%02x:%02x:%02x:%02x:%02x", pValueArr[0], pValueArr[1], pValueArr[2], pValueArr[3], pValueArr[4], pValueArr[5]);
            sprintf(bufSet, "uci set network.lan.macaddr='%02x:%02x:%02x:%02x:%02x:%02x'", pValueArr[0], pValueArr[1], pValueArr[2], pValueArr[3], pValueArr[4], pValueArr[5]);
            break;

        case POPENINF_PORT_2:
            // PRINT_DEBUG("%02x:%02x:%02x:%02x:%02x:%02x", pValueArr[0], pValueArr[1], pValueArr[2], pValueArr[3], pValueArr[4], pValueArr[5]);
            sprintf(bufSet, "uci set network.wan.macaddr='%02x:%02x:%02x:%02x:%02x:%02x'", pValueArr[0], pValueArr[1], pValueArr[2], pValueArr[3], pValueArr[4], pValueArr[5]);
            break;

        case POPENINF_PORT_3:
        case POPENINF_PORT_4:
            break;
            
        default:
            PRINT_WARN("Parameter error[%d]", idx);
            return -1;
    }

    PRINT_DEBUG("%s", bufSet);

    if((fp = popen(bufSet, "w")) == NULL)
    {
        PRINT_WARN("Set failure");
        return -1;
    }
    pclose(fp);
    
    return 0;
}


int PopenInf_Reboot(void)
{
    FILE *fp;

    if((fp = popen("/etc/config/reboot.sh", "w")) == NULL)
    {
        PRINT_WARN("Set failure");
        return -1;
    }
    pclose(fp);
    
    return 0;
}